#include "Buffer.h"

#include <sys/uio.h>
namespace NetWork {

Buffer::Buffer(size_t bufSize): 
    Buffers(bufSize, 0), ReadIndex(0), WriteIndex(0)
{    
}

Buffer::Buffer(Buffer&& o) :
    Buffers(std::move(o.Buffers)), 
    ReadIndex(o.ReadIndex.load()),
    WriteIndex(o.WriteIndex.load())
{
}

Buffer& Buffer::operator=(Buffer&& o)
{
    Buffers = std::move(o.Buffers); 
    ReadIndex = o.ReadIndex.load();
    WriteIndex = o.WriteIndex.load();

    return *this;
}

void Buffer::MakePlace(size_t len)
{   
    //内存腾挪 将 prependable 移除, readIndex 挪动至 0 处
    auto prependSize = GetPrependable() + GetWritable();
    if (len < prependSize) {
        auto readable = GetReadable();

        //左开右闭
        std::copy(&Buffers[ReadIndex], &Buffers[WriteIndex], &Buffers[0]);
        ReadIndex = 0;
        WriteIndex = readable;
    }

    else {
        Buffers.resize(WriteIndex + len);
    }
}

size_t Buffer::GetPrependable() const
{
    return ReadIndex;
}

size_t Buffer::GetReadable() const
{
    return WriteIndex - ReadIndex;
}

size_t Buffer::GetWritable() const
{
    return Buffers.size() - WriteIndex;
}

void Buffer::Retrieve(size_t len)
{
    auto readable = GetReadable();
    len = len > readable ? readable : len;

    ReadIndex += len;
}

void Buffer::RetrieveAll()
{
    ReadIndex = 0;
    WriteIndex = 0;
}

std::vector<char> Buffer::Read()
{
    return Read(GetReadable());
}

std::vector<char> Buffer::Read(size_t len)
{
    auto readable = GetReadable();
    len = len > readable ? readable : len;

    std::vector<char> result(&Buffers[ReadIndex], &Buffers[ReadIndex + len]);
    ReadIndex += len;

    return result;
}

void Buffer::Wirte(const void *buf, size_t len)
{
    auto pBuf = static_cast<const char*>(buf);
    MakePlace(len);
    std::copy(pBuf, pBuf + len, &Buffers[WriteIndex]);
    WriteIndex += len;
}

const char *Buffer::ReadableBegin() const
{
    return Buffers.data() + ReadIndex;
}

const char *Buffer::ReadableEnd() const
{
    return Buffers.data() + WriteIndex;
}

}
